<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        div {
            padding: 2px;
        }
    </style>
</head>

<body>

    <!-- https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/canvas -->
    <!-- <canvas> -->
    <!-- <canvas>元素可被用来通过JavaScript（Canvas API 或 WebGL API）绘制图形及图形动画。 -->

    <!-- Canvas -->
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API -->
    <!-- Canvas API 提供了一个通过JavaScript 和 HTML的<canvas>元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。 -->
    <!-- Canvas API主要聚焦于2D图形。 -->

    <!-- HTMLCanvasElement -->
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement -->
    <!-- HTMLCanvasElement接口提供用于操纵<canvas>元素的布局和表示的属性和方法。 HTMLCanvasElement接口还继承了HTMLElement接口的属性和方法。 -->
    <!-- HTMLCanvasElement.getContext() -->
    <!-- HTMLCanvasElement.getContext() 方法返回canvas 的上下文，如果上下文没有定义则返回 null . -->
    <!-- 在同一个canvas上以相同的 contextType 多次调用此方法只会返回同一个上下文。 -->

    <!-- CanvasRenderingContext2D -->
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D -->

    <div>
        Canvas 的默认大小为300像素×150像素（宽×高，像素的单位是px）。但是，可以使用HTML的高度和宽度属性来自定义Canvas 的尺寸。
    </div>
    <hr>

    <H1>shape 绘制矩形</H1>
    <hr>

    <h4>CanvasRenderingContext2D.rect()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/rect -->
    <!-- CanvasRenderingContext2D.rect() 是 Canvas 2D API 创建矩形路径的方法，矩形的起点位置是 (x, y) ，尺寸为 width 和 height。矩形的4个点通过直线连接，子路径做为闭合的标记，所以你可以填充或者描边矩形。 -->
    <h4>CanvasRenderingContext2D.fill()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/fill -->
    <!-- CanvasRenderingContext2D.fill() 是 Canvas 2D API 根据当前的填充样式，填充当前或已存在的路径的方法。采取非零环绕或者奇偶环绕规则。 -->
    <div>
        <canvas id="mycanvas_01" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doRectAndFill();">rect & fill</button>
    </div>
    <script>
        function doRectAndFill() {
            var canvas = document.getElementById('mycanvas_01');
            var ctx = canvas.getContext('2d');
            ctx.rect(50, 20, 180, 100);
            ctx.fill();
        }
    </script>

    <h4>CanvasRenderingContext2D.stroke()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/stroke -->
    <!-- CanvasRenderingContext2D.stroke() 是 Canvas 2D API 使用非零环绕规则，根据当前的画线样式，绘制当前或已经存在的路径的方法。 -->
    <div>
        <canvas id="mycanvas_02" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doRectAndStroke();">rect & stroke</button>
    </div>
    <script>
        function doRectAndStroke() {
            var canvas = document.getElementById('mycanvas_02');
            var ctx = canvas.getContext('2d');
            ctx.rect(50, 20, 180, 100);
            ctx.stroke();
        }
    </script>
    <hr>

    <h4>CanvasRenderingContext2D.fillRect()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/fillRect -->
    <!-- CanvasRenderingContext2D.fillRect() 是Canvas 2D API 绘制填充矩形的方法。当前渲染上下文中的fillStyle 属性决定了对这个矩形对的填充样式。 -->
    <!-- 这个方法是直接在画布上绘制填充，并不修改当前路径，所以在这个方法后面调用 fill() 或者stroke()方法并不会对这个方法有什么影响。 -->
    <div>
        <canvas id="mycanvas_03" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doFillRect();">getContext</button>
    </div>
    <script>
        function doFillRect() {
            var canvas = document.getElementById('mycanvas_03');
            var ctx = canvas.getContext('2d');
            ctx.fillRect(50, 20, 180, 100);
        }
    </script>
    <hr>

    <h4>CanvasRenderingContext2D.strokeRect()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/strokeRect -->
    <!-- CanvasRenderingContext2D.strokeRect() 是 Canvas 2D API 在 canvas 中，使用当前的绘画样式，描绘一个起点在 (x, y) 、宽度为 w 、高度为 h 的矩形的方法。 -->
    <!-- 此方法直接绘制到画布而不修改当前路径，因此任何后续fill() 或stroke()调用对它没有影响。 -->
    <div>
        <canvas id="mycanvas_04" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doStrokeRect();">strokeRect</button>
    </div>
    <script>
        function doStrokeRect() {
            var canvas = document.getElementById('mycanvas_04');
            var ctx = canvas.getContext('2d');
            ctx.strokeRect(50, 20, 180, 100);
        }
    </script>
    <hr>

    <h4>CanvasRenderingContext2D.clearRect()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/clearRect -->
    <!-- CanvasRenderingContext2D.clearRect()是Canvas 2D API的方法，这个方法通过把像素设置为透明以达到擦除一个矩形区域的目的。 -->
    <div>
        <canvas id="mycanvas_05" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doPrepareRect();">strokeRect</button>
        <button onclick="doClearRectPart();">clearRect(part)</button>
        <button onclick="doClearRectFull();">clearRect(full)</button>
    </div>
    <script>
        function doPrepareRect() {
            var canvas = document.getElementById('mycanvas_05');
            var ctx = canvas.getContext('2d');
            ctx.fillRect(50, 20, 180, 100);
        }
        function doClearRectPart() {
            var canvas = document.getElementById('mycanvas_05');
            var ctx = canvas.getContext('2d');
            ctx.clearRect(20, 10, 150, 60);
        }
        function doClearRectFull() {
            var canvas = document.getElementById('mycanvas_05');
            var ctx = canvas.getContext('2d');
            ctx.clearRect(20, 10, 240, 120);
        }
    </script>


    <hr style="border: red 2px solid;">

    <h1>color 填充和描边样式</h1>

    <hr>

    <h4>CanvasRenderingContext2D.fillStyle</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/fillStyle -->
    <!-- CanvasRenderingContext2D.fillStyle 是Canvas 2D API 使用内部方式描述颜色和样式的属性。默认值是 #000 （黑色）。 -->
    <div>
        <canvas id="mycanvas_06" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doFillStyle();">fillStyle</button>
    </div>
    <script>
        function doFillStyle() {
            var canvas = document.getElementById('mycanvas_06');
            var ctx = canvas.getContext('2d');
            ctx.fillStyle = 'orange';
            // ctx.fillStyle = '#8d6b13';
            ctx.fillRect(50, 20, 180, 100);
        }
    </script>
    <hr>

    <h4>CanvasRenderingContext2D.strokeStyle</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/strokeStyle -->
    <!-- CanvasRenderingContext2D.strokeStyle 是 Canvas 2D API 描述画笔（绘制图形）颜色或者样式的属性。默认值是 #000 (black)。 -->
    <div>
        <canvas id="mycanvas_07" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doStrokeStyle();">strokeStyle</button>
    </div>
    <script>
        function doStrokeStyle() {
            var canvas = document.getElementById('mycanvas_07');
            var ctx = canvas.getContext('2d');
            ctx.strokeStyle = 'orange';
            // ctx.strokeStyle = '#8d6b13';
            ctx.strokeRect(50, 20, 180, 100);
        }
    </script>
    <hr>

    <h1>阴影</h1>
    <hr>


    <h4>CanvasRenderingContext2D.shadowOffsetX</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/shadowOffsetX -->
    <!-- CanvasRenderingContext2D.shadowOffsetX 是 Canvas 2D API 描述阴影水平偏移距离的属性。 -->
    <h4>CanvasRenderingContext2D.shadowOffsetY</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/shadowOffsetY -->
    <!-- CanvasRenderingContext2D.shadowOffsetY 是 Canvas 2D API 描述阴影垂直偏移距离的属性。 -->

    <h4>CanvasRenderingContext2D.shadowBlur</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/shadowBlur -->
    <!-- CanvasRenderingContext2D.shadowBlur 是 Canvas 2D API 描述模糊效果程度的属性； 它既不对应像素值也不受当前转换矩阵的影响。 默认值是 0。 -->
    <div>
        <canvas id="mycanvas_08" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doShadowBlur();">shadowBlur</button>
    </div>
    <script>
        function doShadowBlur() {
            var canvas = document.getElementById('mycanvas_08');
            var ctx = canvas.getContext('2d');
            ctx.shadowBlur = 10;
            ctx.shadowOffsetY = 8;
            ctx.shadowOffsetX = 12;
            ctx.shadowColor = 'orange';
            // ctx.shadowColor = '#8d6b13';
            ctx.strokeRect(50, 20, 180, 100);
        }
    </script>

    <h4>CanvasRenderingContext2D.shadowColor</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/shadowColor -->
    <!-- CanvasRenderingContext2D.shadowColor 是 Canvas 2D API 描述阴影颜色的属性。 -->
    <div>
        <canvas id="mycanvas_09" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doShadowColor();">shadowColor</button>
    </div>
    <script>
        function doShadowColor() {
            var canvas = document.getElementById('mycanvas_09');
            var ctx = canvas.getContext('2d');
            ctx.shadowColor = 'orange';
            // ctx.shadowColor = '#8d6b13';
            ctx.shadowOffsetY = 8;
            ctx.shadowOffsetX = 12;
            ctx.fillStyle = 'blue';
            ctx.fillRect(50, 20, 180, 100);
        }
    </script>
    <div>
        <canvas id="mycanvas_10" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doShadowBlurAndShadowColor();">shadowBlur & shadowColor</button>
    </div>
    <script>
        function doShadowBlurAndShadowColor() {
            var canvas = document.getElementById('mycanvas_10');
            var ctx = canvas.getContext('2d');
            ctx.shadowBlur = 10;
            ctx.shadowColor = 'orange';
            // ctx.shadowColor = '#8d6b13';
            ctx.shadowOffsetY = 8;
            ctx.shadowOffsetX = 12;
            ctx.fillStyle = 'blue';
            ctx.fillRect(50, 20, 180, 100);
            ctx.strokeStyle = 'red';
            ctx.strokeRect(50, 20, 180, 100);
        }
    </script>


    <hr style="border: red 2px solid;">


    <h4>CanvasGradient</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasGradient -->
    <!-- CanvasGradient 接口表示描述渐变的不透明对象。通过 CanvasRenderingContext2D.createLinearGradient() 或 CanvasRenderingContext2D.createRadialGradient() 的返回值得到. -->

    <h4>CanvasGradient.addColorStop()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasGradient/addColorStop -->
    <!-- CanvasGradient.addColorStop() 方法添加一个由偏移值和颜色值指定的断点到渐变。如果偏移值不在0到1之间，将抛出INDEX_SIZE_ERR错误，如果颜色值不能被解析为有效的CSS颜色值 <color>，将抛出SYNTAX_ERR错误。 -->

    <h4>CanvasRenderingContext2D.createLinearGradient()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/createLinearGradient -->
    <!-- CanvasRenderingContext2D.createLinearGradient()方法创建一个沿参数坐标指定的直线的渐变。 -->
    <!-- 该方法返回一个线性 CanvasGradient对象。想要应用这个渐变，需要把这个返回值赋值给 fillStyle 或者 strokeStyle -->
    <div>
        <canvas id="mycanvas_11" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doCreateLinearGradient();">createLinearGradient</button>
        <p>注意：strokeRect和fillRect的第3、4个参数是矩形的宽高度，createLinearGradient的第3、4个参数是矢量的第2个坐标点。</p>
    </div>
    <script>
        function doCreateLinearGradient() {
            var canvas = document.getElementById('mycanvas_11');
            var ctx = canvas.getContext('2d');

            // 绘制线性渐变
            // var gradient = ctx.createLinearGradient(60, 30, 220, 110); // 以当前矩形为基础的矢量坐标
            var gradient = ctx.createLinearGradient(80, 50, 200, 90); // 以当前矩形坐标为基础，矢量起始坐标向内各20个像素。
            gradient.addColorStop(0, 'red');
            gradient.addColorStop(0.5, '#00FF00');
            gradient.addColorStop(1, 'rgb(0, 0, 255)');
            ctx.fillStyle = gradient;
            ctx.fillRect(60, 30, 160, 80);

            // 为了显示过度的起始点（与createLinearGradient参数一致），这里添加矢量线段的绘制，通过矢量线段可以看出渐变的起始点和方向。
            ctx.strokeStyle = 'black';
            ctx.beginPath();
            // ctx.moveTo(60, 30);
            // ctx.lineTo(220, 110);
            ctx.moveTo(80, 50);
            ctx.lineTo(200, 90);
            ctx.stroke();
        }
    </script>

    <h4>CanvasRenderingContext2D.createRadialGradient()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/createRadialGradient -->
    <!-- CanvasRenderingContext2D.createRadialGradient() 是 Canvas 2D API 根据参数确定两个圆的坐标，绘制放射性渐变的方法。这个方法返回 CanvasGradient。 -->
    <div>
        <canvas id="mycanvas_12" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doCreateRadialGradient();">createRadialGradient</button>
    </div>
    <script>
        function doCreateRadialGradient() {
            var canvas = document.getElementById('mycanvas_12');
            var ctx = canvas.getContext('2d');

            // 绘制放射性渐变
            var gradient = ctx.createRadialGradient(150, 75, 20, 180, 80, 75);
            gradient.addColorStop(0, 'red');
            gradient.addColorStop(0.5, '#00FF00');
            gradient.addColorStop(1, 'rgb(0, 0, 255)');
            ctx.fillStyle = gradient;
            ctx.fillRect(0, 0, 300, 150);

            // 为了显示过度的起始圆（与createRadialGradient参数一致），这里添加起始圆的绘制，可以看出渐变的起始变化。
            ctx.strokeStyle = 'black';
            ctx.beginPath();
            ctx.arc(150, 75, 20, 0, 360);
            // ctx.moveTo(255, 80);
            ctx.arc(180, 80, 75, 0, 360);
            ctx.stroke();
        }
    </script>

    <h4>CanvasRenderingContext2D.createPattern()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/createPattern -->
    <!-- CanvasRenderingContext2D.createPattern() 是 Canvas 2D API 使用指定的图像 (CanvasImageSource)创建模式的方法。 它通过repetition参数在指定的方向上重复元图像。此方法返回一个CanvasPattern对象。 -->
    <div>
        <canvas id="mycanvas_13" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doCreatePattern();">createPattern</button>
    </div>
    <script>
        function doCreatePattern() {
            var canvas = document.getElementById('mycanvas_13');
            var ctx = canvas.getContext('2d');

            ctx.rect(10, 10, 280, 130);
            ctx.stroke();
            var img = new Image();
            img.src = 'canvas/Canvas_createpattern.png';
            // img.src = 'canvas/grapefruit-slice-332-332.jpg';
            img.onload = function (event) {
                // var pattern = ctx.createPattern(img, 'repeat');
                var pattern = ctx.createPattern(event.target, 'repeat');
                ctx.fillStyle = pattern;
                ctx.fill();
            };
        }
    </script>
    <div>
        <canvas id="mycanvas_14" style="border: blue 1px solid;" width="520" height="420"></canvas>
        <br>
        <button onclick="doPlayVideo();">createPattern or drawImage
            试试，使用canvas播放一个视频，^_^，如你喜欢，请尝试给它设计一组播放控制按钮吧。</button>
    </div>
    <script>
        var videoIntervalId = undefined;
        function doPlayVideo() {
            if (videoIntervalId != undefined) {
                alert('player is playing, please wait until it completes.');
                return;
            }

            var canvas = document.getElementById('mycanvas_14');
            var ctx = canvas.getContext('2d');

            var video = document.createElement('video');
            video.src = 'canvas/flower.webm';
            // video.src = '../chapter_01/body/周深_郭沁深情对唱《大鱼》.mp4';

            var interval = 10;

            video.onended = function (event) {
                clearInterval(videoIntervalId);
                videoIntervalId = undefined;
                alert('player play completed')
            };

            // video.onloadeddata = function (event) {
            //     video.play();
            //     // 此种方式无法对图片进行缩放处理
            //     videoIntervalId = setInterval(function () {
            //         ctx.rect(10, 10, 500, 400);
            //         var pattern = ctx.createPattern(video, 'no-repeat');
            //         ctx.fillStyle = pattern;
            //         ctx.fill();
            //     }, interval);
            // };

            video.onloadeddata = function (event) {
                video.play();
                videoIntervalId = setInterval(function () {

                    /**         创建一个具有缩放和居中效果的视频播放器的播放拷贝（）        **/

                    // 绘制播放器边框
                    var paddingX = 10;
                    var paddingY = 10;
                    ctx.rect(paddingX, paddingY, canvas.width - paddingX * 2, canvas.height - paddingY * 2);
                    ctx.fill();

                    // 为了实现视频（图片）缩放和居中效果，计算图片缩放的比例和位移。
                    var playerWidth = canvas.width - paddingX * 2;
                    var playerHeight = canvas.height - paddingY * 2;
                    var rateWidth = video.videoWidth / playerWidth;
                    var rateHeight = video.videoHeight / playerHeight;
                    var rateVideoWidthHeight = video.videoWidth / video.videoHeight;
                    var sWidth = 0; // target video width
                    var sHeight = 0; // target video height
                    var dx = 0;
                    var dy = 0;
                    if (rateWidth >= rateHeight) {
                        // 视频宽度占满时，视频高度在播放器内。
                        sWidth = playerWidth;
                        sHeight = sWidth / rateVideoWidthHeight;
                        dy = (playerHeight - sHeight) / 2;
                    } else {
                        // 视频高度占满时，视频宽度在播放器内。
                        sHeight = playerHeight;
                        sWidth = sHeight * rateVideoWidthHeight;
                        dy = (playerHeight - sHeight) / 2;
                    }
                    // 不要忘记播放器还有一个边距
                    dx += paddingX;
                    dy += paddingY;
                    ctx.drawImage(video, dx, dy, sWidth, sHeight);
                    // console.log(`dx=${dx}, dy=${dy}, sWidth=${sWidth}, sHeight=${sHeight}`);
                }, interval);
            };
        }
    </script>


    <hr style="border: red 2px solid;">

    <h1>路径 绘制路径</h1>

    <h4>CanvasRenderingContext2D.beginPath()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/beginPath -->
    <!-- CanvasRenderingContext2D.beginPath() 是 Canvas 2D API 通过清空子路径列表开始一个新路径的方法。 当你想创建一个新的路径时，调用此方法。 -->

    <h4>CanvasRenderingContext2D.closePath()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/closePath -->
    <!-- CanvasRenderingContext2D.closePath() 是 Canvas 2D API 将笔点返回到当前子路径起始点的方法。它尝试从当前点到起始点绘制一条直线。 如果图形已经是封闭的或者只有一个点，那么此方法不会做任何操作。 -->

    <h4>CanvasRenderingContext2D.moveTo()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/moveTo -->
    <!-- CanvasRenderingContext2D.moveTo() 是 Canvas 2D API 将一个新的子路径的起始点移动到(x，y)坐标的方法。 -->

    <h4>CanvasRenderingContext2D.lineTo()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/lineTo -->
    <!-- CanvasRenderingContext2D.lineTo() 是 Canvas 2D API 使用直线连接子路径的终点到x，y坐标的方法（并不会真正地绘制）。 -->

    <div>
        <canvas id="mycanvas_15" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doPath();">beginPath closePath moveTo lineTo</button>
    </div>
    <script>
        function doPath() {
            var canvas = document.getElementById('mycanvas_15');
            var ctx = canvas.getContext('2d');

            // 第一条：折线
            ctx.beginPath();
            ctx.moveTo(10, 10);
            ctx.lineTo(150, 20);
            ctx.lineTo(250, 40);
            ctx.strokeStyle = 'green';
            ctx.stroke();

            // 第二条：封闭
            ctx.beginPath();
            ctx.moveTo(50, 50);
            ctx.lineTo(150, 50);
            ctx.lineTo(150, 150);
            ctx.closePath();
            ctx.strokeStyle = 'orange';
            ctx.stroke();
        }
    </script>
    <hr>

    <h4>CanvasRenderingContext2D.clip()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/clip -->
    <!-- CanvasRenderingContext2D.clip() 是 Canvas 2D API 将当前创建的路径设置为当前剪切路径的方法。 -->

    <div>
        <canvas id="mycanvas_16" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doClip();">clip</button>
    </div>
    <script>
        function doClip() {
            var canvas = document.getElementById('mycanvas_16');
            var ctx = canvas.getContext('2d');

            // ctx.strokeRect(25, 25, 100, 100); // 绘制一个圆的边框方便做对比
            // 创建剪裁区域
            ctx.arc(75, 75, 50, 0, Math.PI * 2, false);
            ctx.clip();

            // 在剪裁区域创建矩形
            ctx.fillStyle = 'blue';
            ctx.fillRect(25, 50, 100, 50);
            // 注：将fillRect拆成rect和fill2个方法，剪裁无效。

        }
    </script>
    <hr>

    <h4>CanvasRenderingContext2D.arc()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/arc -->
    <!-- CanvasRenderingContext2D.arc() 是 Canvas 2D API 绘制圆弧路径的方法。 圆弧路径的圆心在 (x, y) 位置，半径为 r ，根据anticlockwise （默认为顺时针）指定的方向从 startAngle 开始绘制，到 endAngle 结束。 -->
    <div>
        <canvas id="mycanvas_17" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doArc();">arc</button>
    </div>
    <script>
        function doArc() {
            var canvas = document.getElementById('mycanvas_17');
            var ctx = canvas.getContext('2d');
            // 这里，moveTo、lineTo、closePath，用于封边。
            ctx.beginPath();
            ctx.moveTo(75, 75);
            ctx.lineTo(75, 125);
            ctx.arc(75, 75, 50, Math.PI * 0.5, Math.PI * 1.75, false);
            ctx.closePath();
            ctx.stroke();
        }
    </script>

    <h4>CanvasRenderingContext2D.arcTo()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/arcTo -->
    <!-- CanvasRenderingContext2D.arcTo() 是 Canvas 2D API 根据控制点和半径绘制圆弧路径，使用当前的描点(前一个moveTo或lineTo等函数的止点)。根据当前描点与给定的控制点1连接的直线，和控制点1与控制点2连接的直线，作为使用指定半径的圆的切线，画出两条切线之间的弧线路径。 -->
    <div>
        <canvas id="mycanvas_18" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doArcTo();">arcTo</button>
    </div>
    <script>
        function doArcTo() {
            var canvas = document.getElementById('mycanvas_18');
            var ctx = canvas.getContext('2d');
            // 先绘制基础点和2个控制点的线段（即圆的切线）进行对比。
            ctx.beginPath();
            ctx.moveTo(175, 25);    // 基础点
            ctx.lineTo(75, 75);     // 控制点1
            ctx.lineTo(175, 125);   // 控制点2
            ctx.closePath();
            ctx.stroke();
            // 绘制弧线
            ctx.beginPath();
            ctx.moveTo(175, 25)
            ctx.arcTo(75, 75, 175, 125, 25);
            ctx.strokeStyle = 'blue';
            ctx.stroke();
            // 注：目前对于多出来的那条线段，临时没有办法处理。
        }
    </script>
    <hr>

    <h4>CanvasRenderingContext2D.bezierCurveTo()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo -->
    <!-- CanvasRenderingContext2D.bezierCurveTo() 是 Canvas 2D API 绘制三次贝赛尔曲线路径的方法。 该方法需要三个点。 第一、第二个点是控制点，第三个点是结束点。起始点是当前路径的最后一个点，绘制贝赛尔曲线前，可以通过调用 moveTo() 进行修改。 -->
    <div>
        <canvas id="mycanvas_19" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doBezierCurveTo();">bezierCurveTo</button>
    </div>
    <script>
        function doBezierCurveTo() {
            var canvas = document.getElementById('mycanvas_19');
            var ctx = canvas.getContext('2d');
            ctx.beginPath();
            ctx.moveTo(25, 25)
            var cp1x = 150;
            var cp1y = 75;
            var cp2x = 225;
            var cp2y = 100;
            var x = 50;
            var y = 125;
            ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
            ctx.strokeStyle = 'blue';
            ctx.stroke();
            // 注：目前对于多出来的那条线段，临时没有办法处理。
        }
    </script>


    <hr style="border: red 2px solid;">

    <h1>文本样式</h1>

    <h4>CanvasRenderingContext2D.font</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/font -->

    <h4>CanvasRenderingContext2D.textAlign</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/textAlign -->
    <!-- CanvasRenderingContext2D.textAlign 是 Canvas 2D API 描述绘制文本时，文本的对齐方式的属性。注意，该对齐是基于CanvasRenderingContext2D.fillText方法的x的值。所以如果textAlign="center"，那么该文本将画在 x-50%*width。 -->

    <h4>CanvasRenderingContext2D.textBaseline</h4>
    <!-- CanvasRenderingContext2D.textBaseline 是 Canvas 2D API 描述绘制文本时，当前文本基线的属性。 -->

    <h4>CanvasRenderingContext2D.fillText()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/fillText -->
    <!-- CanvasRenderingContext2D.fillText() 是 Canvas 2D API 在 (x, y)位置填充文本的方法。如果选项的第四个参数提供了最大宽度，文本会进行缩放以适应最大宽度。 -->
    <div>
        <canvas id="mycanvas_20" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doFillText();">fillText</button>
    </div>
    <script>
        function doFillText() {
            var canvas = document.getElementById('mycanvas_20');
            var ctx = canvas.getContext('2d');
            ctx.font = 'bold 36px serif';
            ctx.textAlign = 'right';
            ctx.textBaseLine = 'middle';
            ctx.fillText('Hello, World.', 250, 100, 200);
        }
    </script>

    <h4>CanvasRenderingContext2D.strokeText()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/strokeText -->
    <!-- CanvasRenderingContext2D.strokeText() 是 Canvas 2D API 在给定的 (x, y) 位置绘制文本的方法。如果提供了表示最大值的第四个参数，文本将会缩放适应宽度。 -->
    <div>
        <canvas id="mycanvas_21" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doStrokeText();">strokeText</button>
    </div>
    <script>
        function doStrokeText() {
            var canvas = document.getElementById('mycanvas_21');
            var ctx = canvas.getContext('2d');
            ctx.font = 'bold 36px serif';
            ctx.textAlign = 'right';
            ctx.textBaseLine = 'middle';
            ctx.strokeText('Hello, World.', 250, 100, 200);
        }
    </script>

    <hr style="border: red 2px solid;">

    <h1>绘制图像</h1>

    <h4>CanvasRenderingContext2D.drawImage()</h4>
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/drawImage -->
    <!-- Canvas 2D API 中的 CanvasRenderingContext2D.drawImage() 方法提供了多种方式在Canvas上绘制图像。 -->
    <div>
        <p>如感兴趣，可以查看上面createPatternd的一个示例：简易视频播放器（无控制按钮）</p>
        <div>
            <img src="./canvas/rhino.jpg" alt="">
        </div>
        <canvas id="mycanvas_22" style="border: blue 1px solid;"></canvas>
        <br>
        <button onclick="doDrawImage();">strokeText</button>
    </div>
    <script>
        function doDrawImage() {
            var canvas = document.getElementById('mycanvas_22');
            var ctx = canvas.getContext('2d');

            var img = new Image();
            img.src = 'canvas/rhino.jpg';
            img.onload = function (event) {
                var sx = 20;
                var sy = 20;
                var sWidth = 200;
                var sHeight = 120;
                var dx = 30;
                var dy = 30;
                var dWidth = 220;
                var dHeight = 100;
                ctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
            };
        }
    </script>


</body>

</html>